use std::usize;

use crate::{
    nativs::SslMode,
    protocol::{Int1, Int4, NativeCapabilities, NativePacketPayload},
};

// https://dev.mysql.com/doc/dev/mysql-server/latest/group__group__cs__capabilities__flags.html#ga52d3a3f2f6a84a0f427c16bd7bd3df1f
// 低位
pub const CLIENT_LONG_PASSWORD: usize = 1;
pub const CLIENT_FOUND_ROWS: usize = 2;
pub const CLIENT_LONG_FLAG: usize = 4;
pub const CLIENT_CONNECT_WITH_DB: usize = 8;
pub const CLIENT_NO_SCHEMA: usize = 16;
pub const CLIENT_COMPRESS: usize = 32;
pub const CLIENT_ODBC: usize = 64;
pub const CLIENT_LOCAL_FILES: usize = 128;
pub const CLIENT_IGNORE_SPACE: usize = 256;
pub const CLIENT_PROTOCOL_41: usize = 512;
pub const CLIENT_INTERACTIVE: usize = 1024;
pub const CLIENT_SSL: usize = 2048;
pub const CLIENT_IGNORE_SIGPIPE: usize = 4096;
pub const CLIENT_TRANSACTIONS: usize = 8192;
pub const CLIENT_RESERVED: usize = 16384; // for 4.1.0 only
                                          // JDBC: main/protocol-impl/java/com/mysql/cj/protocol/a/NativeServerSession.java
                                          // (removed in 8.0),
// pub const CLIENT_SECURE_CONNECTION: usize = 32768;
pub const CLIENT_RESERVED2: usize = 32768;
// 高位
pub const CLIENT_MULTI_STATEMENTS: usize = 1 << 16;
pub const CLIENT_MULTI_RESULTS: usize = 1 << 17;
pub const CLIENT_PS_MULTI_RESULTS: usize = 1 << 18;
pub const CLIENT_PLUGIN_AUTH: usize = 1 << 19;
pub const CLIENT_CONNECT_ATTRS: usize = 1 << 20;
pub const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: usize = 1 << 21;
pub const CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS: usize = 1 << 22;
pub const CLIENT_SESSION_TRACK: usize = 1 << 23;
pub const CLIENT_DEPRECATE_EOF: usize = 1 << 24;
pub const CLIENT_OPTIONAL_RESULTSET_METADATA: usize = 1 << 25;
pub const CLIENT_ZSTD_COMPRESSION_ALGORITHM: usize = 1 << 26;
pub const CLIENT_QUERY_ATTRIBUTES: usize = 1 << 27;
pub const CLIENT_MULTI_FACTOR_AUTHENTICATION: usize = 1 << 28;
pub const CLIENT_CAPABILITY_EXTENSION: usize = 1 << 29;
pub const CLIENT_SSL_VERIFY_SERVER_CERT: usize = 1 << 30;
pub const CLIENT_REMEMBER_OPTIONS: usize = 1 << 31;

pub const CLIENT_ALL_FLAGS : usize =                                                      
   CLIENT_LONG_PASSWORD | CLIENT_FOUND_ROWS | CLIENT_LONG_FLAG |               
   CLIENT_CONNECT_WITH_DB | CLIENT_NO_SCHEMA | CLIENT_COMPRESS | CLIENT_ODBC | 
   CLIENT_LOCAL_FILES | CLIENT_IGNORE_SPACE | CLIENT_PROTOCOL_41 |             
   CLIENT_INTERACTIVE | CLIENT_SSL | CLIENT_IGNORE_SIGPIPE |                   
   CLIENT_TRANSACTIONS | CLIENT_RESERVED | CLIENT_RESERVED2 |                  
   CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS |  
   CLIENT_SSL_VERIFY_SERVER_CERT | CLIENT_REMEMBER_OPTIONS |                   
   CLIENT_PLUGIN_AUTH | CLIENT_CONNECT_ATTRS |                                 
   CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA |                                     
   CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS | CLIENT_SESSION_TRACK |                
   CLIENT_DEPRECATE_EOF | CLIENT_OPTIONAL_RESULTSET_METADATA |                 
   CLIENT_ZSTD_COMPRESSION_ALGORITHM | CLIENT_QUERY_ATTRIBUTES | CLIENT_MULTI_FACTOR_AUTHENTICATION;


// ServerStatus
pub const SERVER_STATUS_IN_TRANS: usize = 1;
pub const SERVER_STATUS_AUTOCOMMIT: usize = 2;
pub const SERVER_MORE_RESULTS_EXISTS: usize = 8;
pub const SERVER_QUERY_NO_GOOD_INDEX_USED: usize = 16;
pub const SERVER_QUERY_NO_INDEX_USED: usize = 32;
pub const SERVER_STATUS_CURSOR_EXISTS: usize = 64;
pub const SERVER_STATUS_LAST_ROW_SENT: usize = 128;
pub const SERVER_STATUS_DB_DROPPED: usize = 256;
pub const SERVER_STATUS_NO_BACKSLASH_ESCAPES: usize = 512;
pub const SERVER_STATUS_METADATA_CHANGED: usize = 1024;
pub const SERVER_QUERY_WAS_SLOW: usize = 2048;
pub const SERVER_PS_OUT_PARAMS: usize = 4096;
pub const SERVER_STATUS_IN_TRANS_READONLY: usize = 8192;
pub const SERVER_SESSION_STATE_CHANGED: usize = 1 << 14;

#[derive(Debug, Clone)]
pub struct ServerSession {
    ssl_mode: SslMode,
    native_capabilities: Option<NativeCapabilities>,
    capability_flags: usize,

    client_params: Int4,

    auth_switch_request: Option<bool>,
    connected: bool,
}



impl ServerSession {
    pub fn new() -> Self {
        ServerSession {
            ssl_mode: SslMode::DISABLED,
            native_capabilities: None,
            capability_flags: 0,
            client_params: 0,
            auth_switch_request: None,
            connected: false,
        }
    }

    pub fn has_native_capabilities(&mut self) -> bool {
        self.native_capabilities.is_some()
    }

    pub fn get_capability_flags(&mut self) -> usize {
        self.capability_flags
    }

    pub fn is_connected(&self) -> bool {
        self.connected
    }

    pub fn initial_handshake_packet(&mut self, raw: &[u8]) -> NativePacketPayload {
        let initial_handshake_packet = NativePacketPayload::new(raw);
        let mut native_capabilities = NativeCapabilities::new(&initial_handshake_packet);
        native_capabilities.handle();
        self.capability_flags = native_capabilities.get_capability_flags();
        self.native_capabilities = Some(native_capabilities);
        initial_handshake_packet
    }

    // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_response.html
    pub fn connect(&mut self, user: &str, _pass: &str, db: &str) -> Vec<u8> {
        // 组装
        let flags = self.capability_flags;
        let native_capabilities = self.native_capabilities.clone().unwrap();
        let mut buf = native_capabilities.get_initial_handshake_packet();
        buf.reset();
        let client_params = (flags & CLIENT_LONG_PASSWORD) 
            | (flags & CLIENT_FOUND_ROWS)   // 自定义
            | (flags & CLIENT_LONG_FLAG)
            | (flags & if db.is_empty() { 0 } else { CLIENT_CONNECT_WITH_DB })   // 自定义
            | (flags & CLIENT_NO_SCHEMA)    // 自定义
            | (flags & CLIENT_COMPRESS)     // 自定义
            | (flags & CLIENT_PROTOCOL_41)
            | (flags & CLIENT_PLUGIN_AUTH)
            | (flags & CLIENT_DEPRECATE_EOF)  // 使用 OK_Packet 代替 EOF_Packet 
            ;
        
        buf.write_int(crate::nativs::IntegerDataType::INT4, client_params);
        buf.write_int(crate::nativs::IntegerDataType::INT4, 16384);
        buf.write_int(crate::nativs::IntegerDataType::INT1, 255);
        
        buf.write_bytes(crate::nativs::StringSelfDataType::STRING_TERM, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
        buf.write_bytes(crate::nativs::StringSelfDataType::STRING_TERM, user.as_bytes());

        println!("client_params: {client_params}");
        println!("user: {user}");

        buf.get_raw().to_vec()
    }
}

pub fn proceed_handshake_with_pluggable_authentication(challenge: NativePacketPayload) {

    // 生成
}
